using System.Collections.Generic;
using com.youzu.warh.protocol;
using UnityEngine;
using Yoozoo.Gameplay.RTS;
using Yoozoo.Gameplay.RTS.Proto;
using Yoozoo.Modules.InnerCity;
using Coordinate = Yoozoo.Gameplay.RTS.Proto.Coordinate;
using MarchStatus = Yoozoo.Gameplay.RTS.Proto.MarchStatus;
using TargetCoordinateType = Yoozoo.Gameplay.RTS.Proto.TargetCoordinateType;

namespace com.yoozoo.gta.Gameplay.RTS
{
    public static class RtsConvertDataFactory
    {
        public static RtsServerInfo ConvertData(TroopMarch troopMarch,RtsServerInfo serverInfo,LuaArrAccess arrAccess)
        {
            if (serverInfo == null)
            {
                serverInfo = GetServerInfoFromPool();
            }

            var lod3 = troopMarch.lod3;
            serverInfo.tid = lod3.tid;
            serverInfo.Type = troopMarch.lod3.troopType;
            serverInfo.marchStatus = lod3.MarchStatus;
            serverInfo.marchType = troopMarch.lod2.MarchType;
            serverInfo.team = lod3.team;
            serverInfo.troopWorldId = lod3.serverWorldId;
            serverInfo.targetTeam = lod3.targetTeam;
            serverInfo.playerId = lod3.playerId;
            serverInfo.radius = lod3.radius;
            serverInfo.buildingUid = lod3.attachUnit.uid;
            serverInfo.buildType = lod3.attachUnit.type;
            serverInfo.isAssemblyLeader = troopMarch.lod2.isAssemblyLeader;
            serverInfo.assemblyId = troopMarch.lod2.assemblyId;
            //只有侦察行军赋值
            serverInfo.name = troopMarch.lod2.scoutName;

            serverInfo.hero1 = lod3.hero1;
            serverInfo.hero2 = lod3.hero2;
            serverInfo.hero3 = lod3.hero3;

            serverInfo.SoldierType = lod3.soldierType;
            serverInfo.soldierListAccess = arrAccess;
            serverInfo.soldierCount = troopMarch.lod2.soldierCount;
            serverInfo.initSoldierCount = troopMarch.lod2.initSoldierCount;
            serverInfo.SoldierListLength = troopMarch.lod2.soldierListLength;
            serverInfo.visible = lod3.visible;

            if (lod3.heroQualityList!=null)
            {
                serverInfo.heroQualityList = lod3.heroQualityList;
            }

            if (lod3.heroIconList!=null)
            {
                serverInfo.heroIconList = lod3.heroIconList;
            }

            serverInfo.MaxRage = lod3.rageMaxList;
            serverInfo.heroRageList = lod3.heroRageList;

            serverInfo.coordinate = lod3.coordinate;
            serverInfo.pathList = lod3.pathList;
            if (serverInfo.Type == TargetCoordinateType.INTERCITY_TRADE_TRUCK_45)
            {
                MarchHelper.GenerateTradeTruckCoordinateAndPathList(serverInfo);
            }
            else if(serverInfo.Type == TargetCoordinateType.TRAIN_51)
            {
                serverInfo.modelName = "world_trade_train";
            }
            serverInfo.lastFrameTime = lod3.lastFrameTime;
            serverInfo.speed = lod3.speed;
            serverInfo.attRange = troopMarch.lod2.attRange;

            serverInfo.targetId = lod3.targetId;
            serverInfo.targetType = lod3.TargetType;
            serverInfo.attackTargetType = lod3.attackTargetType;
            serverInfo.attackTargetId = GetRealAttackTargetId(lod3.attackTargetId,serverInfo.targetType,serverInfo.targetId);
            
            serverInfo.targetPosition = new Vector3(lod3.targetPosition.xAxis,0,lod3.targetPosition.zAxis);
            serverInfo.isFightConditionNotMet = troopMarch.lod2.isFightConditionNotMet;


            serverInfo.attackTargetUnitType = troopMarch.lod2.attackTargetUnitType;
            serverInfo.besiegeFinalAngle = lod3.besiegeFinalAngle;
            serverInfo.besiegeCenter = lod3.besiegeCenter;
            serverInfo.besiegeRadius = lod3.besiegeRadius;
            serverInfo.attackTargetBuildingId = troopMarch.lod2.attackTargetBuildingId;
            serverInfo.garrisonAngle = troopMarch.lod2.garrisonAngle;

            serverInfo.crossDetail = lod3.crossDetail;

            serverInfo.curHeroIdx = troopMarch.lod2.rageHeroIndex;

            if (serverInfo.Type == TargetCoordinateType.CARGO_TRUCK_42)
            {
                serverInfo.Logo = troopMarch.lod2.Logo;
                serverInfo.LogoColor = troopMarch.lod2.LogoColor;
                serverInfo.LogoBg = troopMarch.lod2.LogoBg;
                serverInfo.LogoBgColor = troopMarch.lod2.LogoBgColor;
            }
            else if (serverInfo.Type == TargetCoordinateType.MARCH_3)
            {
                serverInfo.roleTitle = troopMarch.lod2.roleTitle;
                serverInfo.marchSkinResId = troopMarch.lod2.marchSkinResId;
                // 部队需要判断跨服显示
                if (serverInfo.visible)
                { 
                    serverInfo.visible = serverInfo.troopWorldId <= 0 || serverInfo.troopWorldId == MarchManager.Instance.GetSandBoxServerId();
                }

                // 部队更新一下阵营id
                serverInfo.CampId = troopMarch.CampId;

            }
            else if (serverInfo.Type == TargetCoordinateType.INTERCITY_TRADE_TRUCK_45)
            {
                serverInfo.truckColor = troopMarch.lod3.truckColor;
                serverInfo.truckBeGrabbedTimes = troopMarch.lod3.truckBeGrabbedTimes;
            }
            else if (serverInfo.Type == TargetCoordinateType.TRAIN_51)
            {
                serverInfo.trainBeGrabbedTimes = troopMarch.lod3.truckBeGrabbedTimes;
            }
            serverInfo.leavePveAssemblyId = troopMarch.lod2.leavePveAssemblyId;

            return serverInfo;
        }
        
        public static RtsServerInfo ConvertData(RtsMapMonster monster,RtsServerInfo serverInfo,LuaArrAccess arrAccess)
        {
            if (serverInfo == null)
            {
                serverInfo = GetServerInfoFromPool();
            }

            var lod3 = monster.lod3;
            serverInfo.tid = lod3.npcUid;
            serverInfo.Type = TargetCoordinateType.MONSTER_4;
            serverInfo.marchStatus = lod3.marchStatus;
            serverInfo.team = lod3.team;
            serverInfo.radius = lod3.radius;
            serverInfo.coordinate = lod3.coordinate;
            serverInfo.pathList = lod3.pathList;
            serverInfo.lastFrameTime = lod3.lastFrameTime;
            serverInfo.speed = lod3.speed;
            serverInfo.SoldierType= lod3.soldierType;
            serverInfo.formationId = lod3.fomationId;
            serverInfo.alliandeId = lod3.allianceId;
            serverInfo.coordinate = lod3.coordinate;
            serverInfo.isShowAssemblyHeadFrame = lod3.isShowAssemblyHeadFrame;
            var heroList = lod3.heroList;
            if (heroList!=null)
            {
                var count = heroList.Length;
                if (count >= 1)
                {
                    serverInfo.hero1 = heroList[0];
                }
                if (count >= 2)
                {
                    serverInfo.hero2 = heroList[1];
                }
                if (count >= 3)
                {
                    serverInfo.hero3 = heroList[2];
                }
            }

            serverInfo.level = lod3.level;
            serverInfo.heroIconList = lod3.heroIconList;
            if (lod3.rageMaxList!=null)
            {
                serverInfo.MaxRage = lod3.rageMaxList[0];
            }

            serverInfo.heroRageList = lod3.heroRageList;

            var lod2 = monster.lod2;
            serverInfo.isFightConditionNotMet = lod2.isFightConditionNotMet;
            
            serverInfo.npcType = lod3.npcType;
            serverInfo.heroBgIcon = lod3.heroBgIcon;
            serverInfo.attackTargetId = lod3.attackTargetId;
            serverInfo.attackTargetType = lod3.attackTargetType;
            
            serverInfo.soldierCount = lod2.soldierCount;
            serverInfo.initSoldierCount = lod2.initSoldierCount;

            serverInfo.name = lod2.monsterName;

            serverInfo.targetId = lod2.targetId;
            serverInfo.radarEventQuality = lod2.radarEventQuality;
            serverInfo.radarIcon= lod2.radarIcon;
            serverInfo.radarEventRewardIcon = lod2.radarEventRewardIcon;
            serverInfo.radarEquipType = lod2.radarEquipType;
            serverInfo.radarType = lod2.radarType;
            serverInfo.radarEventType = lod2.radarEventType;

            serverInfo.attRange = lod2.attRange;
            serverInfo.SoldierListLength = lod2.soldierListLength;
                
            serverInfo.curHeroIdx = lod2.rageHeroIndex;

            serverInfo.npcConfigType = lod3.npcConfigType;
          
            return serverInfo;
        }

        public static RtsServerInfo ConvertData(MapAssembly assembly,RtsServerInfo serverInfo,LuaArrAccess arrAccess)
        {
            if (serverInfo == null)
            {
                serverInfo = GetServerInfoFromPool();
            }

            var lod3 = assembly.lod3;
            var lod2 = assembly.lod2;
            var leader = lod3.leader;
            var loaderLod3 = leader.lod3;
            serverInfo.tid = lod3.assemblyId;
            serverInfo.Type = TargetCoordinateType.ASSEMBLY_20;
            serverInfo.marchStatus = loaderLod3.MarchStatus;
            serverInfo.marchType = leader.lod2.MarchType;
            serverInfo.team = loaderLod3.team;

            serverInfo.playerId = loaderLod3.playerId;
            serverInfo.targetTeam = loaderLod3.targetTeam;
            serverInfo.isAssemblyLeader = leader.lod2.isAssemblyLeader;
            serverInfo.assemblyId= leader.lod2.assemblyId;
            serverInfo.leaderTroopId = loaderLod3.tid;
            serverInfo.buildingUid = loaderLod3.attachUnit.uid;
            
            serverInfo.hero1 = lod3.hero1;
            serverInfo.hero2 = lod3.hero2;
            serverInfo.hero3 = lod3.hero3;

            serverInfo.soldierListAccess = arrAccess;
            serverInfo.soldierCount = lod2.soldierCount;
            serverInfo.initSoldierCount = lod2.initSoldierCount;
            serverInfo.SoldierListLength = lod2.soldierListLength;
            serverInfo.visible = loaderLod3.visible;

            serverInfo.heroQualityList = loaderLod3.heroQualityList;
            serverInfo.heroIconList = loaderLod3.heroIconList;
            serverInfo.MaxRage = loaderLod3.rageMaxList;
            serverInfo.heroRageList = loaderLod3.heroRageList;

            serverInfo.coordinate = lod3.coordinate;
            serverInfo.pathList = loaderLod3.pathList;
            serverInfo.lastFrameTime = loaderLod3.lastFrameTime;
            serverInfo.speed = loaderLod3.speed;
            serverInfo.attRange = leader.lod2.attRange;
            
            serverInfo.targetId = lod2.target.targetId;
            serverInfo.targetType = lod2.target.type;
            serverInfo.attackTargetId = GetRealAttackTargetId(assembly.lod3.attackTarget.uid,serverInfo.targetType,serverInfo.targetId);
            serverInfo.attackTargetType = lod3.attackTarget.type;
            serverInfo.isFightConditionNotMet = lod2.isFightConditionNotMet;

            serverInfo.attackTargetUnitType = leader.lod2.attackTargetUnitType;
            serverInfo.besiegeFinalAngle = loaderLod3.besiegeFinalAngle;
            serverInfo.besiegeCenter = loaderLod3.besiegeCenter;
            serverInfo.besiegeRadius = loaderLod3.besiegeRadius;
            serverInfo.attackTargetBuildingId = leader.lod2.attackTargetBuildingId;
            serverInfo.garrisonAngle = leader.lod2.garrisonAngle;

            serverInfo.crossDetail = loaderLod3.crossDetail;

            serverInfo.curHeroIdx = lod2.rageHeroIndex;
            serverInfo.AssemblyIconType = lod3.AssemblyIconType;
            if (string.IsNullOrEmpty(serverInfo.Logo) && !string.IsNullOrEmpty(assembly.lod2.Logo))
            {
                serverInfo.Logo = assembly.lod2.Logo;
                serverInfo.LogoBg = assembly.lod2.LogoBg;
                serverInfo.LogoFrame = assembly.lod2.LogoFrame;
                serverInfo.LogoColor = assembly.lod2.LogoColor;
                serverInfo.LogoBgColor = assembly.lod2.LogoBgColor;
            }
            
            return serverInfo;
        }
        public static RtsServerInfo ConvertData(MapCommonBattleObj battleObj,RtsServerInfo serverInfo,LuaArrAccess access)
        {
            if (serverInfo == null)
            {
                serverInfo = GetServerInfoFromPool();
            }

            serverInfo.tid = battleObj.identity.uid;
            serverInfo.Type = battleObj.identity.type;
            serverInfo.team = battleObj.team;
            serverInfo.coordinate = battleObj.coordinate;
            serverInfo.attackTargetType = battleObj.attackTarget.type;
            serverInfo.attackTargetId = battleObj.attackTarget.uid;
            serverInfo.marchStatus = (MarchStatus) battleObj.marchStatusInt;
            serverInfo.marchType = (MarchType) battleObj.marchTypeInt;
            serverInfo.MaxRage = battleObj.rageMax;
            serverInfo.hero1 = battleObj.hero1;
            serverInfo.hero2 = battleObj.hero2;
            serverInfo.hero3 = battleObj.hero3;
            serverInfo.modelName = battleObj.modelName;
            serverInfo.alliandeId = battleObj.allianceId;
            serverInfo.isNewFromServer = battleObj.isNewFromServer;
            serverInfo.isLoadLod1Hud = false;
            if (serverInfo.formationId!=0)
            {
                if (battleObj.formationId != serverInfo.formationId)
                {
                    serverInfo.needReloadFormation = true;
                }
            }
            serverInfo.formationId = battleObj.formationId;
            if (battleObj.heroIconList!=null)
            {
                serverInfo.heroIconList = battleObj.heroIconList;
            }
            if (battleObj.identity.type == TargetCoordinateType.ALLIANCE_PRACTICE_BOSS_32 || battleObj.identity.type == TargetCoordinateType.DONALD_BOSS_38
                || battleObj.identity.type == TargetCoordinateType.SMUGGLER_30 || battleObj.identity.type == TargetCoordinateType.WORLD_BOSS_44)
            {
                serverInfo.visible = true;
                if (battleObj.identity.type == TargetCoordinateType.DONALD_BOSS_38)
                {
                    serverInfo.radius = battleObj.radius;
                }
            }
            serverInfo.soldierCount = battleObj.soldierCount;
            serverInfo.initSoldierCount = battleObj.initSoldierCount;
            serverInfo.isFightConditionNotMet = battleObj.isFightConditionNotMet;
            serverInfo.DefenceTroop = true;
            serverInfo.level = battleObj.level;
            serverInfo.expireMills = battleObj.expireMills;
            return serverInfo;
        }


        public static RtsServerInfo GetServerInfoFromPool()
        {
            return RTSClassPoolManager.GetRtsServerInfo();
        }

        public static void RecoverServerInfo(RtsServerInfo serverInfo)
        {
            RTSClassPoolManager.RecoverRtsServerInfo(serverInfo);
        }

        private static long GetRealAttackTargetId(long originAttackTargetId,TargetCoordinateType targetType,long marchTarget)
        {
            if (originAttackTargetId == 0)
            {
                return 0;
            }
            if (targetType == TargetCoordinateType.CHECK_POINT_ANNEX_BUILDING_28)
            {
                return marchTarget;
            }
            return originAttackTargetId;
        }

        public static RtsServerInfo ConvertData(RtsArenaTroop troopData,int team,RtsServerInfo serverInfo,LuaArrAccess access)
        {
            if (serverInfo == null)
            {
                serverInfo = GetServerInfoFromPool();
            }

            var troop = troopData.troop;
            serverInfo.tid = troop.troopId;
            serverInfo.Type = TargetCoordinateType.MARCH_3;
            serverInfo.marchStatus = MarchStatus.GARRISON_3;
            serverInfo.marchType = MarchType.GARRISON_2;
            serverInfo.team = team;
            serverInfo.playerName = troopData.playerName;
            serverInfo.targetTeam = 2 - team;
            serverInfo.marchSkinResId = troopData.marchAnimation;
            //serverInfo.playerId = lod3.playerId;
            //serverInfo.buildingUid = lod3.attachUnit.uid;
            //serverInfo.isAssemblyLeader = troopMarch.lod2.isAssemblyLeader;
            //serverInfo.assemblyId = troopMarch.lod2.assemblyId;
            //只有侦察行军赋值
            //serverInfo.name = troopMarch.lod2.scoutName;

            serverInfo.heroQualityList = troopData.heroQualityList;
            serverInfo.heroIconList = troopData.heroIconList;
            serverInfo.heroRageList = troopData.heroRageList;
            if (troop.heroList.Count > 0)
            {
                serverInfo.hero1 = troop.heroList[0].heroId;
                if (troop.heroList.Count > 1)
                {
                    serverInfo.hero2 = troop.heroList[1].heroId;
                    if (troop.heroList.Count > 2)
                    {
                        serverInfo.hero3 = troop.heroList[2].heroId;
                    }
                }
            }
         
            
            serverInfo.SoldierType = (Mathf.FloorToInt(troop.soldier.key / 10f) - 1) % 4 + 1;
            serverInfo.soldierListAccess = access;
            serverInfo.soldierCount = troop.soldier.value;
            serverInfo.initSoldierCount = troop.soldier.value;
            serverInfo.SoldierListLength = 1;
            serverInfo.visible = true;


            serverInfo.MaxRage = troopData.maxRage;

            serverInfo.coordinate = MarchHelper.GetArenaPositionByPosIdAndCamp(troop.initPos,team,troopData.arenaType).ToCoordinate();
            serverInfo.garrisonAngle = team == 0 || team == 1 ? 300 : 120;
            return serverInfo;
        }

        public static RtsServerInfo ConvertData(MarchEntity marchEntity,TroopMarchKeyFrame keyFrame, int team, RtsServerInfo serverInfo, long battleStartTime)
        {
            if (serverInfo == null)
            {
                serverInfo = GetServerInfoFromPool();
            }
  
            serverInfo.team = team;
            serverInfo.targetTeam = 2 - team;
            var modifyFlag = keyFrame.modifyFlag;
            serverInfo.tid = keyFrame.troopId;
            serverInfo.Type = TargetCoordinateType.MARCH_3;
            serverInfo.lastFrameTime = keyFrame.lastFrameTime + battleStartTime;
            var needChangeBesiegeCenter = false;
            if (IsFieldModified(modifyFlag, 4))
            {
                serverInfo.targetId = keyFrame.targetId;
                needChangeBesiegeCenter = true;
            }

            if (IsFieldModified(modifyFlag, 5))
            {
                serverInfo.speed = keyFrame.speed;
            }
            //UnityEngine.Debug.LogError(keyFrame.troopId + " Speed = " + keyFrame.speed + " " + serverInfo.speed);

            if (IsFieldModified(modifyFlag, 6))
            {
                serverInfo.marchStatus = (MarchStatus)(int)keyFrame.marchStatus;
                if (keyFrame.marchStatus == youzu.warh.protocol.MarchStatus.REMOVE_4)
                {
                    serverInfo.marchType = MarchType.DIE_5;
                }
                else
                {
                    serverInfo.marchType = MarchType.ATTACK_1;
                }
            }
            if (IsFieldModified(modifyFlag, 7))
            {
                if (RtsArenaManager.Instance.IsExpeditionReport())
                {
                    serverInfo.besiegeFinalAngle = keyFrame.besiegeFinalAngle;
                    #if UNITY_EDITOR
                                        Debug.Log(keyFrame.troopId + " " + keyFrame.besiegeFinalAngle);
                    #endif
                }
                else
                {
                    if (keyFrame.besiegeFinalAngle < 0)
                    {
                        serverInfo.besiegeFinalAngle = keyFrame.besiegeFinalAngle;
                    }
                    else
                    {
                        serverInfo.besiegeFinalAngle = keyFrame.besiegeFinalAngle - 45;
                        if (serverInfo.besiegeFinalAngle < 0)
                        {
                            serverInfo.besiegeFinalAngle = serverInfo.besiegeFinalAngle + 360;
                        }
                    }
                }

                
                needChangeBesiegeCenter = true;
                serverInfo.besiegeRadius = marchEntity.MarchInfo.besiegeRadius;
                serverInfo.pathList = null;
            }
            if (IsFieldModified(modifyFlag, 8))
            {
                if (keyFrame.attackTarget != null)
                {
                    serverInfo.attackTargetType = TargetCoordinateType.MARCH_3;
                    serverInfo.attackTargetId = keyFrame.attackTarget.uid;
                    if (serverInfo.attackTargetId != 0)
                    {
                        serverInfo.targetId = serverInfo.attackTargetId;
                    }
                    needChangeBesiegeCenter = true;
                }
                else
                {
                    serverInfo.attackTargetId = 0;
                }
            }
            if (IsFieldModified(modifyFlag, 9))
            {
                serverInfo.pathList = GetPathList(keyFrame.pathList);
                /*for (int i = 0; i < keyFrame.pathList.Count; i++)
                {
                    Debug.LogError(keyFrame.troopId + " modified path list " + keyFrame.pathList[i].xAxis + " " +
                                   keyFrame.pathList[i].zAxis);
                }*/
            }
            else
            {
                /*if (serverInfo.pathList != null)
                {
                    for (int i = 0; i < serverInfo.pathList.Length; i++)
                    {
                        Debug.LogError(keyFrame.troopId + " not modified path" + serverInfo.pathList[i].xAxis + " " +
                                       serverInfo.pathList[i].zAxis);
                    }
                }*/
            }
            
            serverInfo.targetType = TargetCoordinateType.MARCH_3;
            serverInfo.coordinate = marchEntity.Position.ToCoordinate();
            if (needChangeBesiegeCenter)
            {
                //找到目标
                var targetId = serverInfo.targetId;
                var target = MarchManager.Instance.GetMarchEntityByIdAndType(targetId,
                    youzu.warh.protocol.TargetCoordinateType.MARCH_3);
                if (target != null)
                {
                    serverInfo.besiegeCenter = target.Position;
                        
                }
            }
            
            //serverInfo.besiegeFinalAngle = keyFrame.besiegeFinalAngle;
            return serverInfo;
        }

        public static bool IsFieldModified(int flag,int position)
        {
            var value = (int)Mathf.Pow(2, position - 1);
            var result = (flag & value) == value;
            return result;
        }
        

        private static Coordinate[] GetPathList(List<youzu.warh.protocol.Coordinate> path)
        {
            var result = new Coordinate[path.Count];
            for (int i = 0; i < path.Count; i++)
            {
                result[i] = new Coordinate{
                    xAxis = path[i].xAxis,
                    zAxis = path[i].zAxis
                };
            }
            return result;
        }
        
        private static LuaArrAccess GetLuaArrAccessByIntPair(IntPair intPair)
        {
            var table = LuaArrAccessAPI.CreateLuaShareAccess();
            table.SetInt(0,intPair.key);
            table.SetInt(1,intPair.value);
            table.SetInt(2,intPair.value);
            table.SetInt(3,5);
            table.SetInt(4,1);
            return table;
        }
    }
}
